package xj.graph2d.app.prop;

import static xj.app.BaseApplicationFrame.getResourceString;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import xj.graph2d.Arrow;
import xj.graph2d.ArrowAttr;
import xj.graph2d.Command;
import xj.graph2d.DrawAttr;
import xj.graph2d.DrawCanvas;
import xj.graph2d.DrawShape;
import xj.graph2d.DrawShapeConstants;
import xj.graph2d.FontAttr;
import xj.graph2d.Group;
import xj.graph2d.OpenShape;
import xj.graph2d.Rotatable;
import xj.graph2d.SimpleDrawDocument;
import xj.graph2d.SimpleDrawView;
import xj.graph2d.TextShape;
import xj.graph2d.app.DrawApp;
import xj.graph2d.command.SetAttrCommand;
import xj.graph2d.command.SetBooleanCommand;
import xj.graph2d.shapes.BoxLabel;
import xj.graph2d.shapes.RoundRectangleShape;
import xj.util.gui.ColoredSquare;

public class DrawShapePropertyPane 
  extends JPanel {

  protected static final int ATTR_PEN_COLOR   = 0;
  protected static final int ATTR_FILL_COLOR  = 1;
  protected static final int ATTR_LINE_STYLE  = 2;
  protected static final int ATTR_LINE_WIDTH  = 3;
  protected static final int ATTR_TAIL_ARROW  = 4;
  protected static final int ATTR_TAIL_SIZE   = 5;
  protected static final int ATTR_HEAD_ARROW  = 6;
  protected static final int ATTR_HEAD_SIZE   = 7;
  protected static final int ATTR_CAP_STYLE   = 8;
  protected static final int ATTR_JOIN_STYLE  = 9;
  protected static final int ATTR_FILLED      = 10;
  protected static final int ATTR_SHOW_BORDER = 11;
  protected static final int ATTR_SHADOW      = 12;
  protected static final int ATTR_BLURED      = 13;
  protected static final int ATTR_FONT        = 14;
  protected static final int ATTR_ROTATION    = 15;
  protected static final int ATTR_ARC_WIDTH   = 16;
  protected static final int ATTR_ARC_HEIGHT  = 17;
  protected static final int ATTR_LAST        = 17;

  protected static String TEXT_PEN_COLOR;
  protected static String TEXT_FILL_COLOR;  
  protected static String TEXT_LINE_STYLE;  
  protected static String TEXT_LINE_WIDTH;  
  protected static String TEXT_TAIL_ARROW;  
  protected static String TEXT_TAIL_SIZE;  
  protected static String TEXT_HEAD_ARROW;  
  protected static String TEXT_HEAD_SIZE;  
  protected static String TEXT_CAP_STYLE;  
  protected static String TEXT_JOIN_STYLE;  
  protected static String TEXT_FILLED;  
  protected static String TEXT_SHOW_BORDER;  
  protected static String TEXT_SHADOW;  
  protected static String TEXT_BLURED;  
  protected static String TEXT_FONT;  
  protected static String TEXT_ROTATION;  
  protected static String TEXT_ARC_WIDTH;  
  protected static String TEXT_ARC_HEIGHT;

  protected static boolean staticInit = false; 

  public DrawShapePropertyPane(DrawApp main) {
    this(main, "Attributes", false);
  }

  public DrawShapePropertyPane(DrawApp main, 
			       String titleString, 
			       boolean border) {
    this.main = main;

    if (!staticInit) { 
      staticInit = true; 
      TEXT_PEN_COLOR   = getResourceString("PenColor.text");
      TEXT_FILL_COLOR  = getResourceString("FillColor.text");
      TEXT_LINE_STYLE  = getResourceString("LineStyle.text");
      TEXT_LINE_WIDTH  = getResourceString("LineWidth.text");
      TEXT_TAIL_ARROW  = getResourceString("TailArrow.text");
      TEXT_TAIL_SIZE   = getResourceString("TailSize.text");
      TEXT_HEAD_ARROW  = getResourceString("HeadArrow.text");
      TEXT_HEAD_SIZE   = getResourceString("HeadSize.text");
      TEXT_CAP_STYLE   = getResourceString("CapStyle.text");
      TEXT_JOIN_STYLE  = getResourceString("JoinStyle.text");
      TEXT_FILLED      = getResourceString("Filled.text");
      TEXT_SHOW_BORDER = getResourceString("ShowBorder.text");
      TEXT_SHADOW      = getResourceString("Shadow.text");
      TEXT_BLURED      = getResourceString("Blured.text");
      TEXT_FONT        = getResourceString("Font.text");
      TEXT_ROTATION    = getResourceString("Rotation.text");
      TEXT_ARC_WIDTH   = getResourceString("ArcWidth.text");
      TEXT_ARC_HEIGHT  = getResourceString("ArcHeight.text");
    }

    //setBackground(Color.white);
    setLayout(new BorderLayout());

    if (border) {
      setBorder(BorderFactory.createEtchedBorder());
    }

    title = new JLabel();
    //title.setFont(Style.editorFont);
    add(title, BorderLayout.NORTH);

    if (titleString != null) {
      title.setText(titleString);
    }

    mainPanel = new GridPanel();

    add(new JScrollPane(mainPanel), BorderLayout.CENTER);

    JButton button;
    penColorIcon = new ColoredSquare(DrawAttr.defaultPenColor, 32, 16);
    button = new IconButton(penColorIcon);
    button.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
    button.setVerticalAlignment(SwingConstants.CENTER);
    button.addActionListener(new ColorListener(penColorIcon));
    addRow(ATTR_PEN_COLOR, TEXT_PEN_COLOR, button);

    fillIcon =  new FillIcon(32, 16);
    DrawShape fillShape = fillIcon.getDrawShape();
    button = new IconButton(fillIcon);
    button.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
    button.setVerticalAlignment(SwingConstants.CENTER);
    gradientListener = new GradientListener();
    gradientListener.setUpdateSystemAttr(false);
    gradientListener.setMain(main);
    gradientListener.setFillIcon(fillIcon);
    gradientListener.setSource(button);
    button.addActionListener(gradientListener);
    addRow(ATTR_FILL_COLOR, TEXT_FILL_COLOR, button);

    lineIcon = new LineWidthIcon(32, 20);
    button = new IconButton(lineIcon);
    button.setBorder(null);
    button.setVerticalAlignment(SwingConstants.CENTER);
    LineWidthSelectionListener lineListener = new LineStyleListener();
    lineListener.setUpdateSystemAttr(false);
    lineListener.setMain(main);
    lineListener.init(lineIcon);
    button.addActionListener(lineListener);
    addRow(ATTR_LINE_STYLE, TEXT_LINE_STYLE, button);

    SpinnerNumberModel lineWidthModel = new SpinnerNumberModel(1, 1, 10, 1);
    lineWidthSpinner = new JSpinner(lineWidthModel);
    lineWidthSpinner.addChangeListener(new SpinnerListener(ATTR_LINE_WIDTH, lineWidthModel));
    addRow(ATTR_LINE_WIDTH, TEXT_LINE_WIDTH, lineWidthSpinner);

    tailIcon = new TailArrowIcon();
    button = new IconButton(tailIcon);
    button.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
    ArrowSelectionListener tailListener = new TailArrowSelectionListener();
    tailListener.setUpdateSystemAttr(false);
    tailListener.setMain(main);
    tailListener.init(tailIcon);
    button.addActionListener(tailListener);
    addRow(ATTR_TAIL_ARROW, TEXT_TAIL_ARROW, button);

    SpinnerNumberModel tailSizeModel = new SpinnerNumberModel(8, 4, 40, 4);
    tailSize = new JSpinner(tailSizeModel);
    tailSize.addChangeListener(new SpinnerListener(ATTR_TAIL_SIZE, tailSizeModel));
    addRow(ATTR_TAIL_SIZE, TEXT_TAIL_SIZE, tailSize);

    headIcon = new HeadArrowIcon();
    button = new IconButton(headIcon);
    button.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
    ArrowSelectionListener headListener = new HeadArrowSelectionListener();
    headListener.setUpdateSystemAttr(false);
    headListener.setMain(main);
    headListener.init(headIcon);
    button.addActionListener(headListener);
    addRow(ATTR_HEAD_ARROW, TEXT_HEAD_ARROW, button);

    SpinnerNumberModel headSizeModel = new SpinnerNumberModel(8, 4, 40, 4);
    headSize = new JSpinner(headSizeModel);
    headSize.addChangeListener(new SpinnerListener(ATTR_HEAD_SIZE, headSizeModel));
    addRow(ATTR_HEAD_SIZE, TEXT_HEAD_SIZE, headSize);

    capIcon = new CapIcon();
    button = new IconButton(capIcon);
    button.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
    CapSelectionListener capListener = new CapSelectionListener();
    capListener.setUpdateSystemAttr(false);
    capListener.setMain(main);
    capListener.init(capIcon);
    button.addActionListener(capListener);
    addRow(ATTR_CAP_STYLE, TEXT_CAP_STYLE, button);

    joinIcon = new JoinIcon();
    button = new IconButton(joinIcon);
    button.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
    JoinSelectionListener joinListener = new JoinSelectionListener();
    joinListener.setUpdateSystemAttr(false);
    joinListener.setMain(main);
    joinListener.init(joinIcon);
    button.addActionListener(joinListener);
    addRow(ATTR_JOIN_STYLE, TEXT_JOIN_STYLE, button);

    filledCheckBox = new JCheckBox("");
    filledCheckBox.setBackground(Color.white);
    filledCheckBox.addActionListener(new CheckBoxListener(ATTR_FILLED, filledCheckBox));
    addRow(ATTR_FILLED, TEXT_FILLED, filledCheckBox);

    showBorderCheckBox = new JCheckBox("");
    showBorderCheckBox.setBackground(Color.white);
    showBorderCheckBox.addActionListener(new CheckBoxListener(ATTR_SHOW_BORDER, showBorderCheckBox));
    addRow(ATTR_SHOW_BORDER, TEXT_SHOW_BORDER, showBorderCheckBox);

    shadowCheckBox = new JCheckBox("");
    shadowCheckBox.setBackground(Color.white);
    shadowCheckBox.addActionListener(new CheckBoxListener(ATTR_SHADOW, shadowCheckBox));
    addRow(ATTR_SHADOW, TEXT_SHADOW, shadowCheckBox);

    bluredCheckBox = new JCheckBox("");
    bluredCheckBox.setBackground(Color.white);
    bluredCheckBox.addActionListener(new CheckBoxListener(ATTR_BLURED, bluredCheckBox));
    addRow(ATTR_BLURED, TEXT_BLURED, bluredCheckBox);

    fontIcon = new FontIcon();
    //button = new JButton(fontIcon);
    button = new IconButton(fontIcon);
    button.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
    fontListener = new FontListener(false, false);
    fontListener.setUpdateSystemAttr(false);
    fontListener.setMain(main);
    fontListener.init(fontIcon);
    fontListener.setSource(button);
    button.addActionListener(fontListener);
    addRow(ATTR_FONT, TEXT_FONT, button);

    SpinnerNumberModel rotationModel = new SpinnerNumberModel(0, 0, 360, 5);
    rotation = new JSpinner(rotationModel);
    rotation.addChangeListener(new SpinnerListener(ATTR_ROTATION, rotationModel));
    addRow(ATTR_ROTATION, TEXT_ROTATION, rotation);

    SpinnerNumberModel arcWidthModel = new SpinnerNumberModel(10, 0, 999, 2);
    arcWidth = new JSpinner(arcWidthModel);
    arcWidth.addChangeListener(new SpinnerListener(ATTR_ARC_WIDTH, arcWidthModel));
    addRow(ATTR_ARC_WIDTH, TEXT_ARC_WIDTH, arcWidth);

    SpinnerNumberModel arcHeightModel = new SpinnerNumberModel(10, 0, 999, 2);
    arcHeight = new JSpinner(arcHeightModel);
    arcHeight.addChangeListener(new SpinnerListener(ATTR_ARC_HEIGHT, arcHeightModel));
    addRow(ATTR_ARC_HEIGHT, TEXT_ARC_HEIGHT, arcHeight);

    disableAll();
  }

  protected void addRow(int i, String left, JComponent right) {
    if (left != null && right != null) {
      JLabel label = new JLabel(left);
      //label.setFont(Style.font);
      //label.setBackground(Color.white);

      mainPanel.addRow(label, right); 
      
      attrNames[i] = label;
      attrValues[i] = right;
    }
  }

  protected void disableAll() {
    setEnabledAll(false);
  }

  protected void setEnabledAll(boolean e) {
    for (int i = 0; i <= ATTR_LAST; i++) {
      attrNames[i].setEnabled(e);
      //attrNames[i].repaint();
      attrValues[i].setEnabled(e);
      //attrValues[i].doLayout();
      //attrValues[i].repaint();
    }
  }

  public void updateAttributes() { 
    show(curShape);
  }

  public void show(DrawShape shape) {
    curShape = shape;
    if (curShape != null) {
      title.setText(getShapeDisplayString(curShape));

      setEnabledAll(true);
      DrawAttr attr = curShape.getDrawAttr();
      if (attr != null) {
	penColorIcon.setColor(attr.getPenColor());
	fillIcon.setDrawAttr(curShape.isFilled(), attr);
	gradientListener.setAttr(curShape.isFilled(), attr); 

	lineIcon.setStyle(attr.getLineStyle());
	lineIcon.setWidth(attr.getPenSize());
	lineWidthSpinner.setValue(new Integer(attr.getPenSize()));
	capIcon.setCapType(attr.getLineCap());
	joinIcon.setJoinType(attr.getLineJoin());

	if (curShape instanceof TextShape) {
	  for (int i = ATTR_LINE_STYLE; i <= ATTR_BLURED; i++) {
	    attrNames[i].setEnabled(false);
	    attrValues[i].setEnabled(false);
	  }
	  FontAttr fa = attr.getFontAttr();
	  fontIcon.setFontName(fa.getFontName());
	  fontIcon.setFontStyle(fa.getFontStyle());
	  fontListener.setAttr(fa);
	} else {
	  attrNames[ATTR_FONT].setEnabled(false);
	  attrValues[ATTR_FONT].setEnabled(false);
	}
      } else {
	// disable
	int i;
	for (i = ATTR_PEN_COLOR; i <= ATTR_LINE_WIDTH; i++) {
	  attrNames[i].setEnabled(false);
	  attrValues[i].setEnabled(false);
	}
      }

      filledCheckBox.setSelected(curShape.isFilled());
      showBorderCheckBox.setSelected(curShape.isShowBorder());
      shadowCheckBox.setSelected(curShape.isShadow());
      bluredCheckBox.setSelected(curShape.isBlured());

      if (curShape instanceof OpenShape) {
	OpenShape oshape = (OpenShape) curShape;
	int size = 8;
	ArrowAttr.ArrowType type = ArrowAttr.ArrowType.NoArrow;
	Arrow headArrow = oshape.getHeadArrow();
	if (headArrow != null) {
	  size = (int) headArrow.getSize();
	  type = headArrow.getType();
	}
	headSize.setValue(new Integer(size));
	headIcon.setArrowType(type);
	size = 8;
	type = ArrowAttr.ArrowType.NoArrow;
	Arrow tailArrow = oshape.getTailArrow();
	if (tailArrow != null) {
	  size = (int) tailArrow.getSize();
	  type = tailArrow.getType();
	}
	tailSize.setValue(new Integer(size));
	tailIcon.setArrowType(type);
      } else {
	for (int i = ATTR_TAIL_ARROW; i <= ATTR_HEAD_SIZE; i++) {
	  attrNames[i].setEnabled(false);
	  attrValues[i].setEnabled(false);
	}
      }

      if (curShape instanceof Rotatable && curShape.isAllowRotation()) {
	float a = curShape.getRotationAngle();
	rotation.setValue(new Integer(
	    (int) (a / DrawShapeConstants.ANGLE_360 * 360.0f)));
      } else {
	attrNames[ATTR_ROTATION].setEnabled(false);
	attrValues[ATTR_ROTATION].setEnabled(false);
      }

      if (curShape instanceof RoundRectangleShape) {
	RoundRectangleShape rrect = (RoundRectangleShape) curShape;
	arcWidth.setValue(new Integer((int) rrect.getArcWidth()));
	arcHeight.setValue(new Integer((int) rrect.getArcHeight()));
      } else {
	attrNames[ATTR_ARC_WIDTH].setEnabled(false);
	attrValues[ATTR_ARC_WIDTH].setEnabled(false);
	attrNames[ATTR_ARC_HEIGHT].setEnabled(false);
	attrValues[ATTR_ARC_HEIGHT].setEnabled(false);
      }
    } else {
      title.setText("");
      disableAll();
    }
    mainPanel.doLayout();
    repaint();
  }

  protected String getShapeDisplayString(DrawShape shape) {
    if (shape != null) {
      String displayName = shape.getDisplayName();
      if (displayName == null || displayName.length() == 0) {
	String tempName = shape.getTemplateName();
	if (tempName != null) {
	  displayName = getResourceString("template." + tempName + ".title");
	  if (displayName == null) {
	    int i = tempName.lastIndexOf(".");
	    if (i >= 0) {
	      displayName = tempName.substring(i + 1);
	    }
	  }
	} else {
	  displayName = shape.getName();
	}
      }
      if (displayName == null) {
	displayName = "";
      }

      if (shape instanceof TextShape) {
	TextShape text = (TextShape) shape;
	String s = text.getWholeString();
	return displayName + " \"" + (s != null ? s : "") + "\"";
      } else if (shape instanceof BoxLabel) {
	return displayName;
      } else if (shape instanceof Group) {
	// return shape.toString();
	return displayName;
      } else {
	return displayName; // + " " + shape.getBoundsString();
      }
    } else {
      return null;
    }
  }

  protected DrawApp main;

  protected DrawShape curShape;

  protected JLabel[] attrNames = new JLabel[ATTR_LAST + 1];

  protected JComponent[] attrValues = new JComponent[ATTR_LAST + 1];

  protected JLabel title;

  protected GridPanel mainPanel;

  // controls 
  
  protected ColoredSquare penColorIcon;

  protected FillIcon fillIcon;

  protected JSpinner lineWidthSpinner;

  protected JSpinner headSize;

  protected JSpinner tailSize;

  protected JSpinner rotation;

  protected JSpinner arcWidth;

  protected JSpinner arcHeight;

  protected LineWidthIcon lineIcon;

  protected TailArrowIcon tailIcon;

  protected HeadArrowIcon headIcon;

  protected CapIcon capIcon;

  protected JoinIcon joinIcon;

  protected FontIcon fontIcon;

  protected JCheckBox filledCheckBox;

  protected JCheckBox showBorderCheckBox;

  protected JCheckBox shadowCheckBox;

  protected JCheckBox bluredCheckBox;

  protected JButton okButton;

  // listeners 

  protected FontListener fontListener;

  protected GradientListener gradientListener;


  class ColorListener implements ActionListener {

    ColorListener(ColoredSquare icon) {
      this.icon = icon;
    }

    public void actionPerformed(ActionEvent e) {
      SimpleDrawDocument doc = main.getDoc();
      SimpleDrawView view = main.getView();
      if (curShape != null) {
	DrawAttr attr = curShape.getDrawAttr();
	if (attr != null) {
	  if (dialog == null) {
	    dialog = new ColorSelectionPanel(main.getJFrame(), 
					     getResourceString("ColorDialog.title"), 
					     attr.getPenColor());
	  } else {
	    dialog.setColor(attr.getPenColor());
	  }

	  boolean okay = dialog.showOptionDialog();

	  if (okay) {
	    if (icon != null) {
	      icon.setColor(dialog.getColor());
	      Object source = e.getSource();
	      if (source instanceof JComponent) {
		((JComponent) source).repaint();
	      }
	    }

	    // update current shape
	    Command cmd = new SetAttrCommand(view, doc, curShape);
	    doc.addCommand(cmd);
	    attr.setPenColor(dialog.getColor());
	    curShape.calculateBounds();
	    DrawCanvas canvas = view.getCanvas();
	    canvas.repaintShape(curShape);
	  }
	}
      }

    }

    protected ColoredSquare icon = null;

    protected ColorSelectionPanel dialog = null;

  }

  class LineStyleListener extends LineWidthSelectionListener {

    @Override
    protected void postAction() {
      lineWidthSpinner.setValue(new Integer(lineIcon.getWidth()));
      lineWidthSpinner.repaint();
    }

  }

  class SpinnerListener implements ChangeListener {

    SpinnerListener(int attrType, SpinnerNumberModel spinnerModel) {
      this.attrType = attrType;
      this.spinnerModel = spinnerModel;
    }

    public void stateChanged(ChangeEvent e) {
      SimpleDrawDocument doc = main.getDoc();
      SimpleDrawView view = main.getView();
      if (curShape != null) {
	Command cmd = new SetAttrCommand(view, doc, curShape);
	doc.addCommand(cmd);

	int v = spinnerModel.getNumber().intValue();
	switch (attrType) {
	case ATTR_LINE_WIDTH:
	  DrawAttr attr = curShape.getDrawAttr();
	  if (attr != null) {
	    attr.setPenSize(v);
	    lineIcon.setWidth(v);
	    attrValues[ATTR_LINE_STYLE].repaint();
	  }
	  break;
	case ATTR_TAIL_SIZE:
	  if (curShape instanceof OpenShape) {
	    OpenShape oshape = (OpenShape) curShape;
	    ArrowAttr tailArrowAttr = oshape.getTailArrow();
	    if (tailArrowAttr == null) {
	      tailArrowAttr = (ArrowAttr) view.getTailArrowAttr().clone();
	    }
	    tailArrowAttr.setSize(v);
	    oshape.setTailArrow(tailArrowAttr);
	  }
	  break;
	case ATTR_HEAD_SIZE:
	  if (curShape instanceof OpenShape) {
	    OpenShape oshape = (OpenShape) curShape;
	    ArrowAttr headArrowAttr = oshape.getHeadArrow();
	    if (headArrowAttr == null) {
	      headArrowAttr = (ArrowAttr) view.getHeadArrowAttr().clone();
	    }
	    headArrowAttr.setSize(v);
	    oshape.setHeadArrow(headArrowAttr);
	  }
	  break;
	case ATTR_ROTATION:
	  if (curShape instanceof Rotatable && curShape.isAllowRotation()) {
	    if (v < 0) {
	      v = 0;
	    } else if (v > 360) {
	      v = v % 360;
	    }
	    curShape
		.setRotationAngle(v / 360.0f * DrawShapeConstants.ANGLE_360);
	  }
	  break;
	case ATTR_ARC_WIDTH:
	  if (curShape instanceof RoundRectangleShape) {
	    RoundRectangleShape rrect = (RoundRectangleShape) curShape;
	    rrect.setArcWidth(v);
	  }
	  break;
	case ATTR_ARC_HEIGHT:
	  if (curShape instanceof RoundRectangleShape) {
	    RoundRectangleShape rrect = (RoundRectangleShape) curShape;
	    rrect.setArcHeight(v);
	  }
	  break;
	}
	curShape.calculateBounds();
	DrawCanvas canvas = view.getCanvas();
	canvas.repaintShape(curShape);
      }
    }

    protected int attrType;

    protected SpinnerNumberModel spinnerModel;

  }

  class CheckBoxListener implements ActionListener {

    CheckBoxListener(int attrType, JCheckBox checkBox) {
      this.attrType = attrType;
      this.checkBox = checkBox;
    }

    public void actionPerformed(ActionEvent e) {

      // System.out.println("CheckBoxListener.stateChanged() attrType=" +
      // attrType);

      SimpleDrawDocument doc = main.getDoc();
      SimpleDrawView view = main.getView();
      if (curShape != null) {
	boolean value = false;
	switch (attrType) {
	case ATTR_FILLED:
	  value = curShape.isFilled();
	  break;
	case ATTR_SHOW_BORDER:
	  value = curShape.isShowBorder();
	  break;
	case ATTR_SHADOW:
	  value = curShape.isShadow();
	  break;
	case ATTR_BLURED:
	  value = curShape.isBlured();
	  break;
	}

	boolean b = checkBox.isSelected();

	if (b != value) {
	  switch (attrType) {
	  case ATTR_FILLED:
	    curShape.setFilled(b);
	    break;
	  case ATTR_SHOW_BORDER:
	    curShape.showBorder(b);
	    break;
	  case ATTR_SHADOW:
	    curShape.setShadow(b);
	    break;
	  case ATTR_BLURED:
	    curShape.setBlured(b);
	    break;
	  }
	  curShape.calculateBounds();
	  DrawCanvas canvas = view.getCanvas();
	  canvas.repaintShape(curShape);

	  Command cmd = new SetBooleanCommand(view, doc, curShape, 
					      attrType - ATTR_FILLED + 1);
	  doc.addCommand(cmd);
	}
      }
    }

    protected int attrType;

    protected JCheckBox checkBox;

  }

}

/**
 *  To fix problem of JButton. Zero size of icon when disabled  
 */
class IconButton extends JButton { 

  public IconButton(Icon icon) { 
    super(icon);
  }

  @Override
  public Dimension getSize(Dimension rv) { 
    if (rv == null) { 
      rv = new Dimension(0, 0);    
    }
    Icon icon = getIcon();
    Insets insets = getInsets();
    rv.width = icon.getIconWidth() + insets.left + insets.right;
    rv.height = icon.getIconHeight() + insets.top + insets.bottom;
    return rv; 
  }

  @Override
  public Dimension getPreferredSize() { 
    Dimension rv = new Dimension(0, 0);        
    Icon icon = getIcon();
    Insets insets = getInsets();
    rv.width = icon.getIconWidth() + insets.left + insets.right;
    rv.height = icon.getIconHeight() + insets.top + insets.bottom;
    return rv; 
  }

  @Override
  public Dimension getMinimumSize() { 
    Dimension rv = new Dimension(0, 0);        
    Icon icon = getIcon();
    Insets insets = getInsets();
    rv.width = icon.getIconWidth() + insets.left + insets.right;
    rv.height = icon.getIconHeight() + insets.top + insets.bottom;
    return rv; 
  }

}
